package ijeoma.tween;

import java.lang.reflect.Method;

import processing.core.PApplet;

public class TweenGroup extends TweenPlugin {
	private int tweenEndedCount = 0;

	private Method tweenGroupStartedMethod, tweenGroupEndedMethod,
			tweenGroupPausedMethod, tweenGroupResumedMethod,
			tweenGroupRepeatedMethod;

	public TweenGroup(PApplet _parent) {
		super(_parent);
		setupEvents();
	}

	public TweenGroup(PApplet _parent, Object[] _tweens) {
		super(_parent, _tweens);
		setupEvents();
	}

	private void setupEvents() {
		try {
			Class<? extends PApplet> parentClass = parent.getClass();
			tweenGroupStartedMethod = parentClass.getMethod(TweenEvent.TWEEN_GROUP_STARTED + "Event", new Class[] { TweenGroup.class });
			tweenGroupEndedMethod = parentClass.getMethod(TweenEvent.TWEEN_GROUP_ENDED + "Event", new Class[] { TweenGroup.class });
			tweenGroupPausedMethod = parentClass.getMethod(TweenEvent.TWEEN_GROUP_PAUSED + "Event", new Class[] { TweenGroup.class });
			tweenGroupResumedMethod = parentClass.getMethod(TweenEvent.TWEEN_GROUP_RESUMED + "Event", new Class[] { TweenGroup.class });
			tweenGroupRepeatedMethod = parentClass.getMethod(TweenEvent.TWEEN_GROUP_REPEATED + "Event", new Class[] { TweenGroup.class });
		} catch (Exception e) {

		}
	}

	public void start() {
		isTweening = true;
		tweenEndedCount = 0;

		dispatchTweenGroupStartedEvent();

		for (int i = 0; i < items.size(); i++) {
			Object currentObject = items.get(i);

			if (currentObject.getClass().getSimpleName().equals("Tween")) {
				((Tween) currentObject).start();
			} else {
				((TweenGroup) currentObject).start();
			}
		}
	}

	public void end() {
		isTweening = false;
		dispatchTweenGroupEndedEvent();
	}

	public void update() {
		if (isTweening) {
			for (int i = 0; i < items.size(); i++) {
				Object currentObject = items.get(i);

				if (currentObject.getClass().getSimpleName().equals("Tween")) {
					((Tween) currentObject).update();
				} else {
					((TweenGroup) currentObject).update();
				}
			}
		}
	}

	public void pause() {
		isTweening = false;

		for (int i = 0; i < items.size(); i++) {
			Object currentObject = items.get(i);

			if (currentObject.getClass().getSimpleName().equals("Tween")) {
				((Tween) currentObject).pause();
			} else {
				((TweenGroup) currentObject).pause();
			}
		}

		dispatchTweenGroupPausedEvent();
	}

	public void resume() {
		isTweening = false;

		for (int i = 0; i < items.size(); i++) {
			Object currentObject = items.get(i);

			if (currentObject.getClass().getSimpleName().equals("Tween")) {
				((Tween) currentObject).resume();
			} else {
				((TweenGroup) currentObject).resume();
			}
		}

		dispatchTweenGroupResumedEvent();
	}

	public void seek(float _time) {
		for (int i = 0; i < items.size(); i++) {
			Object currentObject = items.get(i);

			if (currentObject.getClass().getSimpleName().equals("Tween")) {
				((Tween) currentObject).seek(_time);
			} else {
				((TweenGroup) currentObject).seek(_time);
			}
		}
	}

	public void reverse() {
		for (int i = 0; i < items.size(); i++) {
			Object currentObject = items.get(i);

			if (currentObject.getClass().getSimpleName().equals("Tween")) {
				((Tween) currentObject).reverse();
			} else {
				((TweenGroup) currentObject).reverse();
			}
		}
	}

	public void repeat() {
		super.repeat();

		for (int i = 0; i < items.size(); i++) {
			Object currentObject = items.get(i);

			if (currentObject.getClass().getSimpleName().equals("Tween")) {
				((Tween) currentObject).repeat();
			} else {
				((TweenGroup) currentObject).repeat();
			}
		}
	}

	public void repeat(String _repeatMode) {
		super.repeat();

		for (int i = 0; i < items.size(); i++) {
			Object currentObject = items.get(i);

			if (currentObject.getClass().getSimpleName().equals("Tween")) {
				((Tween) currentObject).repeat(_repeatMode);
			} else {
				((TweenGroup) currentObject).repeat(_repeatMode);
			}
		}
	}

	public void noRepeat() {
		super.noRepeat();

		for (int i = 0; i < items.size(); i++) {
			Object currentObject = items.get(i);

			if (currentObject.getClass().getSimpleName().equals("Tween")) {
				((Tween) currentObject).noRepeat();
			} else {
				((TweenGroup) currentObject).noRepeat();
			}
		}
	}

	public void setRepeatTimes(int _repeatTimes) {
		super.setRepeatTimes(_repeatTimes);

		for (int i = 0; i < items.size(); i++) {
			Object currentObject = items.get(i);

			if (currentObject.getClass().getSimpleName().equals("Tween")) {
				((Tween) currentObject).setRepeatTimes(_repeatTimes);
			} else {
				((TweenGroup) currentObject).setRepeatTimes(_repeatTimes);
			}
		}
	}
	
	public void onTweenEvent(TweenEvent te) {
		if (isDebugging)
			PApplet.println(te + "." + te.type);

		if (te.type.equals(TweenEvent.TWEEN_ENDED)) {
			tweenEndedCount++;

			if (tweenEndedCount == items.size())
				end();
		}
	}

	private void dispatchTweenGroupStartedEvent() {
		if (tweenGroupStartedMethod != null) {
			try {
				tweenGroupStartedMethod.invoke(parent, new Object[] { this });
			} catch (Exception e) {
				System.err.println("Disabling tweenGroupStartedEvent because of an error.");
				e.printStackTrace();
				tweenGroupStartedMethod = null;
			}
		}

		dispatchEvent(TweenEvent.TWEEN_GROUP_STARTED);
	}

	private void dispatchTweenGroupEndedEvent() {
		if (tweenGroupEndedMethod != null) {
			try {
				tweenGroupEndedMethod.invoke(parent, new Object[] { this });
			} catch (Exception e) {
				System.err.println("Disabling tweenGroupEndedEvent because of an error.");
				e.printStackTrace();
				tweenGroupEndedMethod = null;
			}
		}

		dispatchEvent(TweenEvent.TWEEN_GROUP_ENDED);
	}

	private void dispatchTweenGroupPausedEvent() {
		if (tweenGroupPausedMethod != null) {
			try {
				tweenGroupPausedMethod.invoke(parent, new Object[] { this });
			} catch (Exception e) {
				e.printStackTrace();
				tweenGroupPausedMethod = null;
			}
		}

		dispatchEvent(TweenEvent.TWEEN_GROUP_PAUSED);
	}

	private void dispatchTweenGroupResumedEvent() {
		if (tweenGroupResumedMethod != null) {
			try {
				tweenGroupResumedMethod.invoke(parent, new Object[] { this });
			} catch (Exception e) {
				e.printStackTrace();
				tweenGroupResumedMethod = null;
			}
		}

		dispatchEvent(TweenEvent.TWEEN_GROUP_PAUSED);
	}

	private void dispatchTweenGroupRepeatedEvent() {
		if (tweenGroupRepeatedMethod != null) {
			try {
				tweenGroupRepeatedMethod.invoke(parent, new Object[] { this });
			} catch (Exception e) {
				e.printStackTrace();
				tweenGroupRepeatedMethod = null;
			}
		}

		dispatchEvent(TweenEvent.TWEEN_GROUP_REPEATED);
	}

	public String toString() {
		String tweenNames = "";

		for (int i = 0; i < items.size(); i++) {
			Object currentObject = items.get(i);

			if (currentObject.getClass().getSimpleName().equals("Tween")) {
				tweenNames += ((Tween) currentObject).name + ((i < items.size() - 1) ? ", " : "");
			} else {
				tweenNames += ((TweenGroup) currentObject).toString();
			}
		}

		return ("TweenGroup[tweens: {" + tweenNames + "}]");
	}
}
